import React from 'react';
import { Table } from 'antd';
import type { TableProps } from 'antd/es/table';
import type { ColumnType } from 'antd/es/table/interface';
import useVirtualTable from './useVirtualTable';
import styles from './VirtualStickyTable.module.less';

export interface VColumnType<RecordType>
  extends Partial<Omit<ColumnType<RecordType>, 'dataIndex' | 'width'>> {
  dataIndex?: string;
  width: string | number;
  [key: string]: any;
}

export interface VTableProps<RecordType>
  extends Omit<TableProps<RecordType>, 'columns' | 'scroll' | 'components'> {
  columns: ColumnType<RecordType>[];
  // 表格整体高度
  height: number;
  // 行高
  itemHeight?: number;

  // 横向滚动配置
  scroll?: TableProps<RecordType>['scroll'];
  selected?: React.Key[];
  // 单元格属性(eg: onClick)
  OnCell?: (
    item: RecordType,
    // 列配置信息
    col: ColumnType<RecordType>,
    index?: number,
  ) => React.HTMLAttributes<HTMLElement>;
  // 标识列冻结列的className
  fixedClassName: string;
}

const rowHeightMap = {
  small: 20,
  middle: 32,
  large: 40,
};

/**
 * 通过表格 size 获取单元格高度
 * @param size
 */
export function getRowHeight(size: 'small' | 'middle' | 'large' | undefined) {
  if (!size) {
    return rowHeightMap.large;
  }
  return rowHeightMap[size];
}

/**
 * 虚拟滚动表格(支持列冻结)
 */
function VirtualStickyTable<RecordType extends object = any>({
  dataSource,
  columns,
  height = 400,
  size = 'middle',
  bordered,
  pagination,
  rowSelection,
  onRow,
  itemHeight,
  scroll,
  OnCell,
  selected,
  fixedClassName,
  ...props
}: VTableProps<RecordType>) {
  const [data, setData] = React.useState<readonly RecordType[]>(dataSource || []);

  const { renderVirtualList } = useVirtualTable({
    columnList: columns,
    getColumnWidth: (index) => {
      return columns[index as number].width as number;
    },
    render: ({ columnIndex, rowInfo, style, rowIndex }) => {
      const col = columns[columnIndex] || {};
      return (
        <div
          key={columnIndex}
          style={{
            ...style,
            width: col.width,
          }}
          className={`${styles.cell} ${col.className}`}
          {...(OnCell && OnCell(rowInfo as RecordType, col, columnIndex))}
        >
          {col.render
            ? col.render(rowInfo[col.dataIndex as string], rowInfo as RecordType, rowIndex)
            : rowInfo[col.dataIndex as string]}
        </div>
      );
    },
    itemHeight: itemHeight || getRowHeight(size),
    selected,
    tableHeight: height,
    fixedClassName,
  });

  React.useEffect(() => {
    setData(dataSource || []);
  }, [dataSource]);

  return (
    <Table
      {...props}
      dataSource={data}
      columns={columns}
      components={{
        body: renderVirtualList as unknown as any,
      }}
      className={styles.wrapper}
      scroll={scroll}
      size={size}
      bordered={bordered}
      pagination={pagination}
    />
  );
}

export default VirtualStickyTable;
